package cwb1;

import com.google.appengine.api.datastore.*;

import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
import com.google.appengine.api.datastore.Query;

/**
 * The dataEngine uses the design pattern singleton. This class communicates with the database of google. It is very important that you remember that
 * only properties of activities will be saved. When you asks for an activity, the dataEngine searchs the properties in the database and creates with
 * those properties a new activity object.
 * Also uses this class the UserEngine for adding the user to the properties of an activity.
 * 
 * TODO: implementing different options for returning activities.
 * 
 * @author Aurora
 *
 */
public class ActivityRegistry {
	
	
	//The parent key for all activities in the database.
	private Key allActivities = KeyFactory.createKey(Activity.staticGetKind(), "allActivities");
	
	
	//design pattern singleton.
	private static ActivityRegistry instance = new ActivityRegistry();
	
	/**
	 * There is no possibility of creating an object of this class.
	 */
	private ActivityRegistry()
	{
	}
	
	
	
	/**
	 * This method returns the only possible operational instance of the ActivityRegistry class.
	 * 
	 * @return The only possible operational instance of the ActivityRegistry class.
	 */
	public static ActivityRegistry getInstance()
	    {
	        return instance;
	    }
	
	public void add(Activity activity) {
		
		Entity entity = new Entity(createKey(activity));
		DatabaseCommunicator.getInstance().put(entity,activity.getProperties());
		
	}
	
	/**
	 * Returns the activity with the given id.
	 *  
	 * @return The activity with the given id.
	 * @throws EntityNotFoundException When the activity is not found.
	 */
	public Activity get(String activityId, String userId) throws EntityNotFoundException {
		Key userKey = KeyFactory.createKey(allActivities, Activity.staticGetKind(), userId);
		Key activityKey = KeyFactory.createKey(userKey, Activity.staticGetKind(), activityId);
		return ActivityFactory.createActivity(DatabaseCommunicator.getInstance().get(activityKey).getProperties());
	}
	
	public List<Activity> getAllActivitiesUser(String userId) {
		Key userKey = KeyFactory.createKey(allActivities, Activity.staticGetKind(), userId);
		
		return EntityToActivity(DatabaseCommunicator.getInstance().getAll(userKey, Activity.staticGetKind()));
	}
	
	/**
	 * Deletes the activity with the given id, only when the activity is stored without a
	 * user as key.
	 * 
	 * @param activityId The id of the activity.
	 */
	public void delete(Activity activity)
	{
		DatabaseCommunicator.getInstance().delete(createKey(activity));
	}

	
	/**
	 * Returns all the activities in the dataEngine.
	 * 
	 * @return All the activities in the dataEngine.
	 */
	public List<Activity> getAll()
	{
		ArrayList<Activity> activities = new ArrayList<Activity>();
		activities.addAll(EntityToActivity(DatabaseCommunicator.getInstance().getAll(allActivities, Activity.staticGetKind())));
		return activities;	
	}
	
	private List<Activity> EntityToActivity(List<Entity> entities) {
		ArrayList<Activity> activities = new ArrayList<Activity>();
		for(Entity lusEntity : entities) {
			activities.add(ActivityFactory.createActivity(lusEntity.getProperties()));
		}
		return activities;
	}
	
	private Key createKey(Activity activity) {
		Key userKey = KeyFactory.createKey(allActivities, activity.getKind(), activity.getUserId());
		return KeyFactory.createKey(userKey, activity.getKind(), activity.getId());
	}
	
	public List<Activity> getActiveActivity()
	{
		ArrayList<Activity> activeActivities = new ArrayList<Activity>();
		for(Entity lusEntity : DatabaseCommunicator.getInstance().getAll(allActivities, Activity.staticGetKind())) {
			Activity temp = ActivityFactory.createActivity(lusEntity.getProperties());
			if(temp.getStartDate().equals(temp.getStopDate()))
			{
				activeActivities.add(temp);
			}
		}
		return activeActivities;
	}
	
	/**
	 * Returns a list with all the activities of a user of a specific kind.
	 * @param user The activities of the user.
	 * @param kind The type of the activity.
	 * @return A list with all the activities 
	 */
	public List<Activity> getAllActivityUserType(User user, long type) {
		List<Activity> activitiesUser = getAllActivitiesUser(user.getId());
		
		Iterator<Activity> it = activitiesUser.iterator();
		
		while(it.hasNext()) { 
			if(!(it.next().getType() == type) ) {
				it.remove();
			}
		}
		return activitiesUser;
	}
	
	public void update(Activity activity) throws EntityNotFoundException {
		Key activitiesUserKey = KeyFactory.createKey(allActivities, activity.getKind(), activity.getUserId());
		Key activityKey = KeyFactory.createKey(activitiesUserKey, activity.getKind(), activity.getId());
		DatabaseCommunicator.getInstance().put((DatabaseCommunicator.getInstance().get(activityKey)), activity.getProperties());
	}  
}
